﻿using Avalonia.Controls;
using LightCAD.Core.Elements.Basic;
using LightCAD.MathLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Drawing.Actions.Action
{
    public class PointAction : Curve2dAction
    {
        private PointAction() { }

        public PointAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Point");
        }


        private static readonly LcCreateMethod[] CreateMethods;

        static PointAction()
        {
            CreateMethods = new LcCreateMethod[1];         //这行代码创建了一个名为 'CreateMethods' 的静态数组，该数组的长度为1。这个数组似乎用于存储 'LcCreateMethod' 对象。
            CreateMethods[0] = new LcCreateMethod()       //在数组的第一个位置，也就是索引为0的位置，创建了一个 'LcCreateMethod' 对象。这个对象似乎用于描述某种创建方法，具体来说，这里描述了一个名为 "2P" 的创建方法，其描述为 "两点创建直线"。
            {
                Name = "P",
                Description = "创建点",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name = "Step0", Options = "指定一个点/输入坐标值:" },
                }
            };
        }

        internal static void Initilize()
        {
            ElementActions.Point = new PointAction();
            LcDocument.ElementActions.Add(BuiltinElementType.Point, ElementActions.Point);
        }


        private List<Vector2> points;

        private Vector2 Point { get; set; }

        private PointInputer inputer { get; set; }



        //绘点
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            DocumentManager.CurrentRecorder.BeginAction("Point");
            
            this.points = new List<Vector2>();

            this.inputer = new PointInputer(this.docEditor);
            var curMethod = CreateMethods[0];

        Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await inputer.Execute(step0.Options);

            if(inputer.isCancelled)
            {
                this.Cancel();
                goto End;
            }

            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }

            if(inputer!=null)
            {
                if (result0.ValueX == null)
                {
                    if (result0.Option != null)
                    {
                        goto Step0;
                    }
                }
                this.Point = (Vector2)result0.ValueX;
                points.Add(Point);
                this.vportRt.ActiveElementSet.AddPoint(Point);
                goto Step0;
            }

            

        End:
            this.inputer = null;
            this.EndCreating();

            if (this.points.Count > 0)
            {
                DocumentManager.CurrentRecorder.EndAction();
            }
            else
            {
                DocumentManager.CurrentRecorder.CancleAction();
            }
        }

        public override void Draw(SKCanvas canvas, LcElement element, Vector2 offset)
        {
            var grp = element as LcPoint;
            var point = this.vportRt.ConvertWcsToScr(grp.Point);

            float changeNum = 1;
            using (var pen = new SKPaint { Color = SKColors.Gray, IsStroke = false })
            {
                canvas.DrawRect((float)point.X - changeNum, (float)point.Y - changeNum, changeNum * 2, changeNum * 2, pen); //正方形色块
            }



            ////var eleAction = (ele.RtAction as ElementAction);

            ////eleAction.SetViewport(this.vportRt).Draw(canvas, ele, offset);

            //double changeNum = 1;

            //SKPoint topLeft = new SKPoint((float)(point.X - changeNum), (float)(point.Y + changeNum));
            //SKPoint topRight = new SKPoint((float)(point.X + changeNum), (float)(point.Y + changeNum));
            //SKPoint bottomRight = new SKPoint((float)(point.X + changeNum), (float)(point.Y - changeNum));
            //SKPoint bottomLeft = new SKPoint((float)(point.X - changeNum), (float)(point.Y - changeNum));

            //canvas.DrawLine(topLeft, topRight, Constants.draggingPen);
            //canvas.DrawLine(topRight, bottomRight, Constants.draggingPen);
            //canvas.DrawLine(bottomRight, bottomLeft, Constants.draggingPen);
            //canvas.DrawLine(bottomLeft, topLeft, Constants.draggingPen);

        }

        //获取选中状态
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var point = element as LcPoint; //getHel
            var grips = new List<ControlGrip>();
            var gripCenter = new ControlGrip
            {
                Element = point,
                Name = "Point",
                Position = point.Point
            };
            grips.Add(gripCenter);
            return grips.ToArray();
        }


        //捕捉
        public override SnapPointResult SnapPoint(SnapRuntime snapRt, LcElement element, Vector2 point, bool forRef, Vector2 PrePoint = null)
        {

            var maxDistance = vportRt.GetSnapMaxDistance();
            var poi = element as LcPoint;
            var sscur = SnapSettings.Current;
            var result = new SnapPointResult { Element = element };
            var ipoint = poi.GetCurves()[0];

            if (sscur.ObjectOn)
            {

                if (sscur.PointType.Has(SnapPointType.Center))
                {
                    if ((point - poi.Point).Length() <= maxDistance)
                    {
                        result.Point = poi.Point;
                        result.Name = "Center";
                        result.Curves.Add(new SnapRefCurve(SnapPointType.Center, ipoint));
                    }
                }
            }
            if (result.Point != null)
                return result;
            else
                return null;
        }


        //拖拽
        private string _gripName;

        private Vector2 _position;

        private LcPoint _point;
        public Vector2 PrePoint { get; set; }
        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            var point = element as LcPoint;
            _point = point;


            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                Vector2 dragpoint = position;

                if (this.vportRt.SnapRt?.Current != null)
                {
                    dragpoint = this.vportRt.SnapRt.Current.SnapPoint;
                }
                else if (gripName == "Point")
                {
                    point.Set(dragpoint);
                }
            }
        }

        //拖拽渲染
        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_position != null)
            {
                var wc = this.vportRt.ConvertWcsToScr(_position).ToSKPoint();
                float changeNum = 4;
                using (var pen = new SKPaint { Color = SKColors.Blue, IsStroke = false })
                {
                    canvas.DrawRect(wc.X - changeNum, wc.Y - changeNum, changeNum * 2, changeNum * 2, pen); //正方形色块
                }
            }
        }

        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>()
                       {
                           new PropertyObserver()
                               {
                                    Name = "PointX",
                                    DisplayName = "位置 X 坐标",
                                    CategoryName = "Geometry",
                                    CategoryDisplayName = "几何图形",
                                    Getter = (ele) => (ele as LcPoint).Point.X,
                                    Setter = (ele, value) =>
                                       {
                                           var point = (ele as LcPoint);
                                           var x = Convert.ToDouble(value);
                                           var poi = new Vector2(x);
                                           point.Set(point: poi);
                                       }
                               },
                           new PropertyObserver()
                               {
                                    Name = "PointY",
                                    DisplayName = "位置 Y 坐标",
                                    CategoryName = "Geometry",
                                    CategoryDisplayName = "几何图形",
                                    Getter = (ele) => (ele as LcPoint).Point.Y,
                                    Setter = (ele, value) =>
                                       {
                                           var point = (ele as LcPoint);
                                           var y = Convert.ToDouble(value);
                                           var poi = new Vector2(y);
                                           point.Set(point: poi);
                                       }
                               },
                       };
        }
    }
}
